---
title: "Example: Conditional Branching | Workflows | Kastrax Docs"
description: Example of using Kastrax to create conditional branches in workflows using the `branch` statement .
---

import { GithubLink } from "@/components/github-link";

# Workflow with Conditional Branching ✅

Workflows often need to follow different paths based on some condition.
This example demonstrates how to use the `branch` construct to create conditional flows within your workflows.


## Define Planning Agent ✅
Define a planning agent which leverages an LLM call to plan activities given a location and corresponding weather conditions.

```ts showLineNumbers copy filename="agents/planning-agent.ts"
import { Agent } from '@kastrax/core/agent'
import { openai } from '@ai-sdk/openai'

const llm = openai('gpt-4o')

const planningAgent = new Agent({
  name: 'planningAgent',
  model: llm,
  instructions: `
        You are a local activities and travel expert who excels at weather-based planning. Analyze the weather data and provide practical activity recommendations.

        📅 [Day, Month Date, Year]
        ═══════════════════════════

        🌡️ WEATHER SUMMARY
        • Conditions: [brief description]
        • Temperature: [X°C/Y°F to A°C/B°F]
        • Precipitation: [X% chance]

        🌅 MORNING ACTIVITIES
        Outdoor:
        • [Activity Name] - [Brief description including specific location/route]
          Best timing: [specific time range]
          Note: [relevant weather consideration]

        🌞 AFTERNOON ACTIVITIES
        Outdoor:
        • [Activity Name] - [Brief description including specific location/route]
          Best timing: [specific time range]
          Note: [relevant weather consideration]

        🏠 INDOOR ALTERNATIVES
        • [Activity Name] - [Brief description including specific venue]
          Ideal for: [weather condition that would trigger this alternative]

        ⚠️ SPECIAL CONSIDERATIONS
        • [Any relevant weather warnings, UV index, wind conditions, etc.]

        Guidelines:
        - Suggest 2-3 time-specific outdoor activities per day
        - Include 1-2 indoor backup options
        - For precipitation >50%, lead with indoor activities
        - All activities must be specific to the location
        - Include specific venues, trails, or locations
        - Consider activity intensity based on temperature
        - Keep descriptions concise but informative

        Maintain this exact formatting for consistency, using the emoji and section headers as shown.
      `,
})

export { planningAgent }
```

## Define Weather Workflow ✅
Define the weather workflow with 3 steps: one to fetch the weather via a network call, one to plan activities, and another to plan only indoor activities.
Both using the planning agent.

```ts showLineNumbers copy filename="workflows/conditional-workflow.ts"
import { z } from 'zod'
import { createStep, createWorkflow } from './vNext'


function getWeatherCondition(code: number): string {
  const conditions: Record<number, string> = {
    0: 'Clear sky',
    1: 'Mainly clear',
    2: 'Partly cloudy',
    3: 'Overcast',
    45: 'Foggy',
    48: 'Depositing rime fog',
    51: 'Light drizzle',
    53: 'Moderate drizzle',
    55: 'Dense drizzle',
    61: 'Slight rain',
    63: 'Moderate rain',
    65: 'Heavy rain',
    71: 'Slight snow fall',
    73: 'Moderate snow fall',
    75: 'Heavy snow fall',
    95: 'Thunderstorm',
  }
  return conditions[code] || 'Unknown'
}

const forecastSchema = z.object({
  date: z.string(),
  maxTemp: z.number(),
  minTemp: z.number(),
  precipitationChance: z.number(),
  condition: z.string(),
  location: z.string(),
})

// Fetch weather step
const fetchWeather = createStep({
  id: 'fetch-weather',
  description: 'Fetches weather forecast for a given city',
  inputSchema: z.object({
    city: z.string(),
  }),
  outputSchema: forecastSchema,
  execute: async ({ inputData }) => {
    if (!inputData) {
      throw new Error('Trigger data not found')
    }

    const geocodingUrl = `https://geocoding-api.open-meteo.com/v1/search?name=${encodeURIComponent(inputData.city)}&count=1`
    const geocodingResponse = await fetch(geocodingUrl)
    const geocodingData = (await geocodingResponse.json()) as {
      results: { latitude: number; longitude: number; name: string }[]
    }

    if (!geocodingData.results?.[0]) {
      throw new Error(`Location '${inputData.city}' not found`)
    }

    const { latitude, longitude, name } = geocodingData.results[0]

    const weatherUrl = `https://api.open-meteo.com/v1/forecast?latitude=${latitude}&longitude=${longitude}&current=precipitation,weathercode&timezone=auto,&hourly=precipitation_probability,temperature_2m`
    const response = await fetch(weatherUrl)
    const data = (await response.json()) as {
      current: {
        time: string
        precipitation: number
        weathercode: number
      }
      hourly: {
        precipitation_probability: number[]
        temperature_2m: number[]
      }
    }

    const forecast = {
      date: new Date().toISOString(),
      maxTemp: Math.max(...data.hourly.temperature_2m),
      minTemp: Math.min(...data.hourly.temperature_2m),
      condition: getWeatherCondition(data.current.weathercode),
      location: name,
      precipitationChance: data.hourly.precipitation_probability.reduce(
        (acc, curr) => Math.max(acc, curr),
        0
      ),
    }

    return forecast
  },
})

// Plan activities indorrs or outdoors
const planActivities = createStep({
  id: 'plan-activities',
  description: 'Suggests activities based on weather conditions',
  inputSchema: forecastSchema,
  outputSchema: z.object({
    activities: z.string(),
  }),
  execute: async ({ inputData, kastrax }) => {
    console.log('planActivities')
    const forecast = inputData

    if (!forecast) {
      throw new Error('Forecast data not found')
    }

    const prompt = `Based on the following weather forecast for ${forecast.location}, suggest appropriate activities:
      ${JSON.stringify(forecast, null, 2)}
      `

    const agent = kastrax?.getAgent('planningAgent')
    if (!agent) {
      throw new Error('Planning agent not found')
    }

    const response = await agent.stream([
      {
        role: 'user',
        content: prompt,
      },
    ])

    let activitiesText = ''

    for await (const chunk of response.textStream) {
      process.stdout.write(chunk)
      activitiesText += chunk
    }

    return {
      activities: activitiesText,
    }
  },
})

// Plan indoor activities only
const planIndoorActivities = createStep({
  id: 'plan-indoor-activities',
  description: 'Suggests indoor activities based on weather conditions',
  inputSchema: forecastSchema,
  outputSchema: z.object({
    activities: z.string(),
  }),
  execute: async ({ inputData, kastrax }) => {
    console.log('planIndoorActivities')
    const forecast = inputData

    if (!forecast) {
      throw new Error('Forecast data not found')
    }

    const prompt = `In case it rains, plan indoor activities for ${forecast.location} on ${forecast.date}`

    const agent = kastrax?.getAgent('planningAgent')
    if (!agent) {
      throw new Error('Planning agent not found')
    }

    const response = await agent.stream([
      {
        role: 'user',
        content: prompt,
      },
    ])

    let activitiesText = ''

    for await (const chunk of response.textStream) {
      process.stdout.write(chunk)
      activitiesText += chunk
    }

    return {
      activities: activitiesText,
    }
  },
})

const weatherWorkflow = createWorkflow({
  id: 'weather-workflow-step2-if-else',
  inputSchema: z.object({
    city: z.string().describe('The city to get the weather for'),
  }),
  outputSchema: z.object({
    activities: z.string(),
  }),
})
  .then(fetchWeather)
  .branch([
    [
      async ({ inputData }) => {
        return inputData?.precipitationChance > 50
      },
      planIndoorActivities,
    ],
    [
      async ({ inputData }) => {
        return inputData?.precipitationChance <= 50
      },
      planActivities,
    ],
  ])

weatherWorkflow.commit()

export { weatherWorkflow }
```

```ts showLineNumbers copy filename="index.ts"
import { Kastrax } from '@kastrax/core/kastrax'
import { createLogger } from '@kastrax/core/logger'
import { weatherWorkflow } from './workflows'
import { planningAgent } from './agents'

const kastrax = new Kastrax({
  vnext_workflows: {
    weatherWorkflow,
  },
  agents: {
    planningAgent,
  },
  logger: createLogger({
    name: 'Kastrax',
    level: 'info',
  }),
})

export { kastrax }
```

## Register Agent and Workflow instances with Kastrax class ✅
Register the agents and workflow with the kastrax instance.
This is critical for enabling access to the agents within the workflow.

```ts showLineNumbers copy filename="index.ts"
import { Kastrax } from '@kastrax/core/kastrax'
import { createLogger } from '@kastrax/core/logger'
import { weatherWorkflow } from './workflows'
import { planningAgent } from './agents'

const kastrax = new Kastrax({
  vnext_workflows: {
    weatherWorkflow,
  },
  agents: {
    planningAgent,
  },
  logger: createLogger({
    name: 'Kastrax',
    level: 'info',
  }),
})

export { kastrax }
```

## Execute the weather workflow ✅
Here, we'll get the weather workflow from the kastrax instance, then create a run and execute the created run with the required inputData.

```ts showLineNumbers copy filename="exec.ts"
import { kastrax } from "./"

const workflow = kastrax.vnext_getWorkflow('weatherWorkflow')
const run = workflow.createRun()

const result = await run.start({ inputData: { city: 'New York' } })
console.dir(result, { depth: null })
```

<br />
<br />
<hr className="dark:border-[#404040] border-gray-300" />
<br />
<br />
<GithubLink
  link={'https://github.com/kastrax-ai/kastrax/blob/main/examples/basics/workflows/conditional-branching'}
/>

